import 'dart:async' as asy;
import 'dart:math' as math;
import 'dart:math';
import 'dart:ui';
import 'package:bot_toast/bot_toast.dart';
import 'package:flame/box2d/box2d_component.dart';
import 'package:flame/box2d/box2d_game.dart';
import 'package:flame/components/component.dart';
import 'package:flame/flame.dart';
import 'package:flame/game.dart';
import 'package:flame/palette.dart';
import 'package:flame/position.dart' as flame;
import 'package:flame/sprite.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:box2d_flame/box2d.dart';
import 'package:flutterzhuyili/main.dart';
import 'package:flutterzhuyili/page/ball/top-display.dart';
import 'package:flutterzhuyili/utils/shared_preferences_keys.dart';

import 'backyard.dart';
import 'boundaries.dart';

bool isTra = false;
bool pauseTheGame = false;
bool canClick = false;

//void main() async {
//  WidgetsFlutterBinding.ensureInitialized();
//  await Flame.util.fullScreen();
//  final MyBox2D box = MyBox2D();
//  final MyGame game = MyGame(box);
//  BotToastInit();
//  runApp(game.widget);
//}

class BallPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final MyBox2D box = MyBox2D();
    final MyGame game = MyGame(box);
    return Scaffold(
      body: Column(
        children: <Widget>[
          Expanded(
            child: game.widget,
          ),
        ],
      ),
    );
  }
}

class Ball extends BodyComponent {
  Paint originalPaint, currentPaint;
  bool giveNudge = true;
  Sprite showSprite;
  final MyGame myGame;
  double _trueRadius = 0; //真实的直径
  double orRadius; //原始传入的系数
  bool isGone = false;
  bool isTheGoal = false;
  Sprite successSprite = Sprite('files/ball/rollball_success.png');
  Sprite questionSprite = Sprite('files/ball/rollball_question.png');
  bool isWait = false;

  Ball(
    this.myGame, {
    Key key,
    this.orRadius = 5.0,
    this.isTheGoal = false,
    Vector2 position,
    Box2DComponent box,
  }) : super(box) {
    originalPaint = _randomPaint();
    currentPaint = originalPaint;
    final Vector2 worldPosition = viewport.getScreenToWorld(position);
    _createBody(orRadius, worldPosition);
    _trueRadius = orRadius * box.viewport.scale * window.devicePixelRatio;
    showSprite =
        Sprite('files/ball/rollball_sprite_${Random().nextInt(10) + 1}.png');
  }

  Paint _randomPaint() {
    math.Random rng = math.Random();
    return PaletteEntry(Color.fromARGB(100 + rng.nextInt(155),
            100 + rng.nextInt(155), 100 + rng.nextInt(155), 255))
        .paint;
  }

  void _createBody(double radius, Vector2 position) {
    final CircleShape shape = CircleShape();
    shape.radius = radius;

    final fixtureDef = FixtureDef()
      ..shape = shape
      ..restitution = 1.0
      ..density = 1.0
      ..friction = 0.0;

    final bodyDef = BodyDef()
      // To be able to determine object in collision
      ..setUserData(this)
      ..position = position
      ..type = BodyType.DYNAMIC;

    body = world.createBody(bodyDef)..createFixtureFromFixtureDef(fixtureDef);
  }

  @override
  bool destroy() {
    return isGone;
  }

  @override
  void renderCircle(Canvas c, Offset p, double radius) {
    showSprite.renderCentered(
      c,
      flame.Position.fromOffset(p),
      size: flame.Position.fromSize(Size(
          5 * box.viewport.scale * window.devicePixelRatio,
          5 * box.viewport.scale * window.devicePixelRatio)),
    );
//    );
  }

  @override
  void update(double t) {
    super.update(t);

    if (isTra) {
      originalPaint = BasicPalette.white.paint;
      currentPaint = BasicPalette.white.paint;
    }
    if (giveNudge) {
      body.applyLinearImpulse(
          Vector2(0, (math.Random().nextInt(20) - 10) * 1000.0),
          body.getLocalCenter(),
          true);
      body.applyLinearImpulse(
          Vector2((math.Random().nextInt(20) - 10) * 1000.0, 0),
          body.getLocalCenter(),
          true);
      giveNudge = false;
    }
  }

  bool isClick(TapDownDetails details) {
    var center = Vector2.zero();
    final CircleShape circle = body.getFixtureList().getShape();
    body.getWorldPointToOut(circle.p, center);
    center = viewport.getWorldToScreen(center);

    var dx = details.localPosition.dx - center.x;
    var dy = details.localPosition.dy - center.y;
    var distance = math.sqrt(dx * dx + dy * dy);
    if (distance < _trueRadius) {
      //说明点击了这个东西
      return true;
    }
    return false;
  }

  void onTapDown(TapDownDetails details) {}

  void success() {
    showSprite.image = successSprite.image;

//    body.applyTorque(12);
//    body.setFixedRotation(true);
  }

  void waitToClick() {
    showSprite.image = questionSprite.image;
  }
}

class WhiteBall extends Ball {
  WhiteBall(MyGame myGame, Vector2 position, Box2DComponent box)
      : super(myGame, position: position, box: box) {
    originalPaint = BasicPalette.white.paint;
    currentPaint = originalPaint;
  }
}

class MyGame extends Box2DGame with HasWidgetsOverlay {
  Size screenSize;
  double tileSize;
  BallTopDisplay ballTopDisplay;
  Backyard background;
  List<Ball> balls = [];
  int level = 1;

  asy.Timer _timer;

  MyGame(Box2DComponent box) : super(box) {
    init();
  }

  void init() async {
    resize(await Flame.util.initialDimensions());
    final List<BodyComponent> boundaries = createBoundaries(box);
    if (sp.hasKey(SharedPreferencesKeys.ballLevel)) {
      level = sp.getInt(SharedPreferencesKeys.ballLevel);
    }
    box.addAll(boundaries);
    background = Backyard(this);
    ballTopDisplay = BallTopDisplay(this, level);
    initBalls();
  }

  void pauseOrResumeGame() {
    pauseTheGame = !pauseTheGame;
  }

  @override
  void render(Canvas c) {
    c.translate(0, 0);
    if (background != null) background.render(c);
    if (ballTopDisplay != null) ballTopDisplay.render(c);
    super.render(c);
  }

  void initBalls() {
    if (_timer != null) _timer.cancel();
    pauseTheGame = false;
    canClick = false;
    const tenMs = const Duration(milliseconds: 1000);
    _timer = asy.Timer.periodic(tenMs, (timer) {
      if (balls.length > level + 2) {
        canClick = true;
        _timer.cancel();
        balls.forEach((element) {
          element.waitToClick();
        });
        pauseTheGame = true;
        return;
      }
      Ball ball;
      if (balls.isEmpty) {
        ball = Ball(this,
            position: Vector2(
                math.Random().nextInt(100) * screenSize.width / 100,
                (math.Random().nextInt(90) + 10) * screenSize.height / 100),
            box: box,
            isTheGoal: true);
      } else {
        ball = Ball(this,
            position: Vector2(
                math.Random().nextInt(100) * screenSize.width / 100,
                (math.Random().nextInt(90) + 10) * screenSize.height / 100),
            box: box);
      }
      add(ball);
      balls.add(ball);
    });
  }

  @override
  void resize(Size size) {
    super.resize(size);
    screenSize = size; //370 850
    tileSize = screenSize.width / 9;
  }

  @override
  void onTapDown(TapDownDetails details) {
    super.onTapDown(details);
    ballTopDisplay.onTapDown(details);
//    print('${details.globalPosition.dx}   ${details.globalPosition.dy}');
    if (!canClick) return;

    balls.forEach((element) {
      if (element.isClick(details)) {
        if (element.isTheGoal) {
          balls.forEach((element) {
            element.body.setType(BodyType.STATIC);
          });
          element.success();
          level++;
          sp.putInt(SharedPreferencesKeys.ballLevel, level);
          addWidgetOverlay(
              'nextLevelWidget',
              Center(
                child: RaisedButton(
                  color: Colors.green,
                  child: Container(
                    height: 150,
                    width: 120,
                    child: const Center(
                      child: const Text(
                        '下一关',
                        style: TextStyle(color: Colors.white, fontSize: 18),
                      ),
                    ),
                  ),
                  shape: const RoundedRectangleBorder(
                      borderRadius:
                          BorderRadius.all(const Radius.circular(360))),
                  onPressed: () {
                    ballTopDisplay.updateLevel(level);
                    removeWidgetOverlay('nextLevelWidget');
                    balls.forEach((element) {
                      box.world.destroyBody(element.body);
                    });
                    background.randomBackyard();
                    balls.clear();
                    initBalls();
                  },
                ),
              ));
        } else {
          //走点错了的逻辑
          clickErrorGoal();
        }
        return;
      }
    });

//    box.components.forEach((element) {
//      if (element is Ball) {
//        var center = Vector2.zero();
//        final CircleShape circle = body.getFixtureList().getShape();
//        body.getWorldPointToOut(circle.p, center);
//        center = viewport.getWorldToScreen(center);
//        if (element.rect.contains(details.globalPosition)) {
//          musicButton.onTapDown();
//        }
//      }
//    }

//    if (math.Random().nextInt(10) < 2) {
//      add(WhiteBall(position, box));
//    } else {
//    add(Ball(this, position, box));
//    }
  }

  void clickErrorGoal() {
    addWidgetOverlay(
        'againLevelWidget',
        Center(
          child: RaisedButton(
            color: Colors.greenAccent,
            child: Container(
              height: 150,
              width: 120,
              child: const Center(
                child: const Text(
                  '再来一次',
                  style: TextStyle(color: Colors.white, fontSize: 18),
                ),
              ),
            ),
            shape: const RoundedRectangleBorder(
                borderRadius: BorderRadius.all(const Radius.circular(360))),
            onPressed: () {
              ballTopDisplay.updateLevel(level);
              removeWidgetOverlay('againLevelWidget');
              balls.forEach((element) {
                box.world.destroyBody(element.body);
              });
              balls.clear();
              initBalls();
            },
          ),
        ));
  }
}

class MyBox2D extends Box2DComponent {
  MyBox2D() : super(scale: 5.0, gravity: 0.0);

  @override
  void render(canvas) {
    super.render(canvas);
    canvas.translate(0, 0);
  }

  @override
  void update(t) {
    if (pauseTheGame) {
      return;
    }
    super.update(t);
  }

  @override
  void initializeWorld() {}
}
